home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
SBDAC.ARJ
/
DACDMA.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-09
|
5KB
|
223 lines
/* Output to SB DAC using DMA mode */
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <io.h>
#include <alloc.h>
#include <dos.h>
#include <stdlib.h>
#include <alloc.h>
/* Defines for Soundblaster and Soundblaster Pro IO address */
#define LEFT_FM_STATUS 0x00 /* Pro only */
#define LEFT_FM_ADDRESS 0x00 /* Pro only */
#define LEFT_FM_DATA 0x01 /* Pro only */
#define RIGHT_FM_STATUS 0x02 /* Pro only */
#define RIGHT_FM_ADDRESS 0x02 /* Pro only */
#define RIGHT_FM_DATA 0x03 /* Pro only */
#define MIXER_ADDRESS 0x04 /* Pro only */
#define MIXER_DATA 0x05 /* Pro only */
#define DSP_RESET 0x06
#define FM_STATUS 0x08
#define FM_ADDRESS 0x08
#define FM_DATA 0x09
#define DSP_READ_DATA 0x0A
#define DSP_WRITE_DATA 0x0C
#define DSP_WRITE_STATUS 0x0C
#define DSP_DATA_AVAIL 0x0E
#define CD_ROM_DATA 0x10 /* Pro only */
#define CD_ROM_STATUS 0x11 /* Pro only */
#define CD_ROM_RESET 0x12 /* Pro only */
#define CD_ROM_ENABLE 0x13 /* Pro only */
#define ADLIB_FM_STATUS 0x388
#define ADLIB_FM_ADDRESS 0x388
#define ADLIB_FM_DATA 0x389
/* Defines for 8237 DMA Controller IO addresses */
#define DMA 0x00
#define CH0_BASE DMA+0
#define CH0_COUNT DMA+1
#define CH1_BASE DMA+2
#define CH1_COUNT DMA+3
#define CH2_BASE DMA+4
#define CH2_COUNT DMA+5
#define CH3_BASE DMA+6
#define CH3_COUNT DMA+7
#define DMA_STATUS DMA+8
#define DMA_CMD DMA+8
#define DMA_REQUEST DMA+9
#define DMA_MASK DMA+10
#define DMA_MODE DMA+11
#define DMA_FF DMA+12
#define DMA_TMP DMA+13
#define DMA_CLEAR DMA+13
#define DMA_CLRMSK DMA+14
#define DMA_WRMSK DMA+15
#define DMAPAGE 0x80
int InitSB(void);
extern unsigned IOaddr;
extern unsigned IRQ;
void far interrupt (*OldIRQ)();
volatile int DMA_complete;
/* Define a useful macro for writing data to the DAC */
#define writedac(x) { while(inportb(IOaddr+DSP_WRITE_STATUS) & 0x80); \
outportb(IOaddr+DSP_WRITE_DATA,(x)); }
/* Interrupt handler for DMA complete IRQ from Soundblaster */
void far interrupt SBHandler()
{
enable();
DMA_complete = 1;
outportb(0x20,0x20);
}
/* Sets the sample rate to be used for digitising or playback */
void SetSampleRate(unsigned rate)
{
unsigned char tc;
tc = (unsigned char)(256 - (1000000/rate));
writedac(0x40); /* Command byte for sample rate */
writedac(tc); /* Sample rate time constant */
}
void SetVoice(int state)
{
writedac((state) ? 0xd1 : 0xd3); /* Command bytes for voice: */
/* 0xD1 - voice on */
/* 0xD3 - voice off */
}
void OutVoice(char *data, unsigned dlen)
{
int t;
long addr;
register int i;
unsigned char im, tm;
DMA_complete = 0;
/* Enable interrupts on PIC */
im = inportb(0x21);
tm = ~(1 << IRQ);
outportb(0x21,im & tm);
enable();
/* Set DMA mode */
outportb(DMA_MASK,5);
outportb(DMA_FF,0);
outportb(DMA_MODE,0x49);
/* Set transfer address */
addr = ((long)FP_SEG(data) << 4) + (long)FP_OFF(data);
t = (int)(addr >> 16);
outportb(DMAPAGE+3,t);
t = (int)(addr & 0xffff);
outportb(CH1_BASE,t & 0xff);
outportb(CH1_BASE,t >> 8);
/* Set transfer length byte count */
outportb(CH1_COUNT,dlen & 0xff);
outportb(CH1_COUNT,dlen >> 8);
/* Unmask DMA channel */
outportb(DMA_MASK,1);
/* Setup Soundblaster for transfer */
writedac(0x48); /* One command byte used for DMA DAC transfer */
/* Write length */
writedac(dlen & 0xff);
writedac(dlen >> 8);
writedac(0x14); /* Second command byte for DMA DAC transfer */
/* Write length */
writedac(dlen & 0xff);
writedac(dlen >> 8);
}
void main(int argc, char *argv[])
{
FILE *f;
char *raw;
long sample_len;
register int j, i;
unsigned sl, tmp, nr, sr;
unsigned char tm;
if(argc < 2)
{
puts("Usage: dacdma sample [sample rate]");
exit(1);
}
if(InitSB())
{
printf("Could not find Soundblaster!\n");
exit(1);
}
printf("Found Soundblaster at %xh.\n",IOaddr);
f = fopen(argv[1],"rb");
if(f == NULL)
{
printf("Could not open sample file %s\n",argv[1]);
exit(1);
}
sample_len = filelength(fileno(f));
if(sample_len > 64000)
sl = 64000;
else
sl = (int)sample_len;
raw = (signed char *)farmalloc((unsigned long)sl);
nr = fread(raw,1,sl,f);
fclose(f);
/* Insert our IRQ handler into interrupt chain */
disable();
OldIRQ = getvect(0x08 + IRQ);
setvect(0x08 + IRQ,SBHandler);
enable();
sr = 11000;
if(argc == 3)
sr = atoi(argv[2]);
SetSampleRate(sr);
SetVoice(1);
OutVoice(raw,sl);
while(!kbhit() && !DMA_complete)
;
if(!DMA_complete)
getch();
SetVoice(0);
/* Restore old IRQ vector */
disable();
setvect(0x08 + IRQ,OldIRQ);
tm = inportb(0x21);
outportb(0x21,tm | (1 << IRQ));
enable();
farfree(raw);
exit(0);
}